"""
邮件发送服务
"""
import smtplib
import ssl
import asyncio
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
from typing import Dict, Any, Optional
from models.email_config import EmailConfig


class EmailService:
    """邮件发送服务"""

    def __init__(self):
        pass

    async def send_email_async(self, email_config: EmailConfig, to_email: str, 
                              to_name: Optional[str], subject: str, content: str,
                              attachments: Optional[list] = None) -> Dict[str, Any]:
        """异步发送邮件"""
        try:
            # 在线程池中执行同步的邮件发送
            loop = asyncio.get_event_loop()
            result = await loop.run_in_executor(
                None, 
                self._send_email_sync, 
                email_config, to_email, to_name, subject, content, attachments
            )
            return result
        except Exception as e:
            return {
                "success": False,
                "error": str(e)
            }

    def _send_email_sync(self, email_config: EmailConfig, to_email: str, 
                        to_name: Optional[str], subject: str, content: str,
                        attachments: Optional[list] = None) -> Dict[str, Any]:
        """同步发送邮件"""
        try:
            # 创建邮件消息
            msg = MIMEMultipart('alternative')
            msg['From'] = f"{email_config.from_name} <{email_config.from_email}>"
            msg['To'] = f"{to_name} <{to_email}>" if to_name else to_email
            msg['Subject'] = subject

            # 添加邮件内容
            # 假设内容是HTML格式
            html_part = MIMEText(content, 'html', 'utf-8')
            msg.attach(html_part)

            # 添加附件（如果有）
            if attachments:
                for attachment in attachments:
                    self._add_attachment(msg, attachment)

            # 创建SMTP连接
            if email_config.use_ssl:
                # 使用SSL连接
                context = ssl.create_default_context()
                server = smtplib.SMTP_SSL(email_config.smtp_host, email_config.smtp_port, context=context)
            else:
                # 使用普通连接
                server = smtplib.SMTP(email_config.smtp_host, email_config.smtp_port)
                if email_config.use_tls:
                    # 启用TLS
                    server.starttls()

            # 登录SMTP服务器
            if email_config.username and email_config.password:
                server.login(email_config.username, email_config.password)

            # 发送邮件
            text = msg.as_string()
            server.sendmail(email_config.from_email, to_email, text)
            server.quit()

            return {
                "success": True,
                "message": "邮件发送成功",
                "message_id": msg.get('Message-ID')
            }

        except smtplib.SMTPAuthenticationError as e:
            return {
                "success": False,
                "error": f"SMTP认证失败: {str(e)}"
            }
        except smtplib.SMTPRecipientsRefused as e:
            return {
                "success": False,
                "error": f"收件人被拒绝: {str(e)}"
            }
        except smtplib.SMTPServerDisconnected as e:
            return {
                "success": False,
                "error": f"SMTP服务器连接断开: {str(e)}"
            }
        except smtplib.SMTPException as e:
            return {
                "success": False,
                "error": f"SMTP错误: {str(e)}"
            }
        except Exception as e:
            return {
                "success": False,
                "error": f"发送邮件失败: {str(e)}"
            }

    def _add_attachment(self, msg: MIMEMultipart, attachment: Dict[str, Any]):
        """添加附件"""
        try:
            # 支持两种附件格式：
            # 1. 包含content的直接内容格式
            # 2. 包含file_path的文件路径格式
            filename = attachment.get('filename') or attachment.get('original_filename')
            content = attachment.get('content')
            file_path = attachment.get('file_path')
            content_type = attachment.get('content_type', 'application/octet-stream')

            if not filename:
                print("附件缺少文件名")
                return

            # 如果没有直接内容，尝试从文件路径读取
            if not content and file_path:
                try:
                    import os
                    if os.path.exists(file_path):
                        with open(file_path, 'rb') as f:
                            content = f.read()
                        print(f"从文件路径读取附件: {file_path}, 大小: {len(content)} bytes")
                    else:
                        print(f"附件文件不存在: {file_path}")
                        return
                except Exception as read_error:
                    print(f"读取附件文件失败: {str(read_error)}")
                    return

            if not content:
                print("附件内容为空")
                return

            # 创建附件部分
            part = MIMEBase('application', 'octet-stream')
            part.set_payload(content)
            encoders.encode_base64(part)
            part.add_header(
                'Content-Disposition',
                f'attachment; filename="{filename}"'
            )
            msg.attach(part)
            print(f"成功添加附件: {filename}")

        except Exception as e:
            # 附件添加失败，记录错误但不影响邮件发送
            print(f"添加附件失败: {str(e)}")
            import traceback
            traceback.print_exc()

    def test_email_connection(self, email_config: EmailConfig) -> Dict[str, Any]:
        """测试邮件连接"""
        try:
            # 创建SMTP连接
            if email_config.use_ssl:
                context = ssl.create_default_context()
                server = smtplib.SMTP_SSL(email_config.smtp_host, email_config.smtp_port, context=context)
            else:
                server = smtplib.SMTP(email_config.smtp_host, email_config.smtp_port)
                if email_config.use_tls:
                    server.starttls()

            # 测试登录
            if email_config.username and email_config.password:
                server.login(email_config.username, email_config.password)

            server.quit()

            return {
                "success": True,
                "message": "邮件服务器连接成功"
            }

        except smtplib.SMTPAuthenticationError as e:
            return {
                "success": False,
                "error": f"SMTP认证失败: {str(e)}"
            }
        except smtplib.SMTPServerDisconnected as e:
            return {
                "success": False,
                "error": f"SMTP服务器连接失败: {str(e)}"
            }
        except smtplib.SMTPException as e:
            return {
                "success": False,
                "error": f"SMTP错误: {str(e)}"
            }
        except Exception as e:
            return {
                "success": False,
                "error": f"连接测试失败: {str(e)}"
            }

    async def send_test_email_async(self, email_config: EmailConfig, to_email: str) -> Dict[str, Any]:
        """异步发送测试邮件"""
        subject = "邮件配置测试"
        content = """
        <html>
        <body>
            <h2>邮件配置测试</h2>
            <p>这是一封测试邮件，用于验证邮件配置是否正确。</p>
            <p>如果您收到这封邮件，说明邮件配置已经成功！</p>
            <hr>
            <p><small>此邮件由邮件统一发送平台自动发送</small></p>
        </body>
        </html>
        """
        
        return await self.send_email_async(
            email_config=email_config,
            to_email=to_email,
            to_name=None,
            subject=subject,
            content=content
        )
